#!/usr/bin/python 
import sys , time , threading , re , os
from optparse import OptionParser
from sqlgroup import *
os.chdir( os.path.dirname(os.path.realpath(__file__)) )
from configger import *
from groupmanager import *
sys.path.append("plugins")

class Main(object):

	RUNNER 	= True
	parsers = {}
	gms	= {}

	def __init__(self,debug=False):
		self.conf 		= Configger(debug)
		self.conf.parse_groups()
		self.logger 		= self.conf.logger
		if debug : self.logger.setVerbose()
		self.init_parsers()
                for group_name in self.conf.gc :
			if "ssh" in  self.conf.gc[group_name]["group_conf"] and "hosts" in self.conf.gc[group_name]["group_conf"]["ssh"]:
				self.gms[group_name] = PairGroupManager(group_name, self.conf.gc[group_name]["group_conf"] , self.conf.gc[group_name]["compare_conf"],self.parsers[group_name],self.logger)
			elif "db_conf" in self.conf.gc[group_name] :
				self.gms[group_name] = SqlGroup(group_name,self.conf.gc[group_name]["db_conf"] , 
					self.conf.gc[group_name]["group_conf"] , self.conf.gc[group_name]["compare_conf"], self.logger)
			else :
	                        self.gms[group_name] = GroupManager(group_name, self.conf.gc[group_name]["group_conf"] , self.conf.gc[group_name]["compare_conf"],self.parsers[group_name],self.logger)


	def init_parsers(self):
		for group_name in self.conf.gc :
			if not "parser" in self.conf.gc[group_name]["group_conf"] : continue
			pf = self.conf.gc[group_name]["group_conf"]["parser"]
			try:
				module 				= __import__(pf)
				if pf == "regexparse":
					self.parsers[group_name]        = module.Parser(self.conf.gc[group_name]["group_conf"]["regex"],self.conf.gc[group_name]["group_conf"]["fields"])
				else :
					self.parsers[group_name] 	= module.Parser()
			except Exception,e:
				self.logger._log("groups.log" , "Can not load parser %s in plugin folder\n ERROR : %s" % (pf , str(e)))
				print "Can not load parser %s in plugin folder" % (pf)	
				self.conf.gc[group_name] = None
				

	def run(self):

		while True:
			self.logger._log("groups.log" , "loop...")
			if self.conf.is_config_changed(): 
				self.logger._log("groups.log" , "group.conf file CHANGED")
				self.__init__()
			for group_name in self.conf.gc :
				if isinstance(self.gms[group_name] , SqlGroup):
					threading.Thread(target=self.gms[group_name].pulse ).start()
				elif isinstance(self.gms[group_name] , PairGroupManager):
					threading.Thread(target=self.gms[group_name].run  ,  args=(0 ,) ).start()
					threading.Thread(target=self.gms[group_name].run  ,  args=(1 ,) ).start()
				else :
					threading.Thread(target=self.gms[group_name].run).start()	
			
			time.sleep(self.conf.server_values["pulse_sec"])			

			for group_name in self.conf.gc :
				if isinstance(self.gms[group_name] , SqlGroup): continue
				self.gms[group_name].RUNNER = False	# 	stop thread from getting I/O data
				time.sleep(1)				#	Let the threade safly close I/O connection
				self.gms[group_name].pulse()

			

	#	RUN SINGLE PULSE NOT ENDLESS
	def run_single(self , cmd):
		self.logger._log("groups.log" , "START Signle Run on CMD %s" % (cmd))
		print "START Signle Run on CMD %s" % (cmd)
		_thrds = []

		for group_name in self.conf.gc :
			if isinstance(self.gms[group_name] , PairGroupManager):
				self.logger._log("groups.log" , "%s\tERROR , Can not run single mode in Pair mode. SKIIPED" % (group_name))
				print "%s\tERROR , Can not run single mode in Pair mode. SKIIPED" % (group_name)
				continue

			_t = threading.Thread(target=self.gms[group_name].single ,  args=(cmd,))
			_t.start()
			_thrds.append( _t )

		for _t in _thrds :
			_t.join()

		self.logger._log("groups.log" , "FINISH Signle Run on CMD %s" % (cmd))
		print "FINISH Signle Run on CMD %s" % (cmd)

#########################################################################

def parse_args():
        parser = OptionParser()
        parser.add_option("-f", "--f", action="store_false" , dest="f", help="Run permanently. use the groups.conf as config file. default" , default='')
        parser.add_option("-d","--debug",dest="debug",action="store_false" , default=None,help="All Loggers will be STDOUT")
	parser.add_option("-s" , "--s3" , dest="s" , default=None , help="run in S3 mode . extract 2 files from s3 as resource. Expecting {parametes}")
	parser.add_option("-q" , "--sql" , dest="q" , default=None , help="run in sql mode . compare 2 time range data from a table. Expecting {parametes}")
        parser.add_option("-z" , "--headtail" , dest="ht" , default=None , help="head tail mode. compare head and tail from same file")
        parser.add_option("-t" , "--test" , dest="test" , action="store_false" , default=None , help="test configuration. Print to STDOUT and exit.")
        parser.add_option("-e" , "--examples" , action="store_false" , dest="e" , default=None , help="print basic examples")
        return parser.parse_args()

#########################################################################

def print_examples():
	print "***	Run in Permanent Mode using the groups.conf config file:"
	print "%s/%s\n" % (os.path.dirname(os.path.realpath(__file__)) , __file__)
	print "***      Run in Head Tail Mode giving number as argument for extracted rows:"
	print "		Extracting 5000 rows from head and tail and under go comparison:"
	print "%s/%s -t 5000\n" % (os.path.dirname(os.path.realpath(__file__)) , __file__)
	print "***      Run in S3 mode. giving server name and 2 hours"
	print "		this mode will download this files and made the comparison with "
	print "		arguments defined as input:"
	print """%s/%s -s '{"fields": ["b","bv","cc"] ,  "sumfields":{"count":0.5}  , "faults_min":10 , "minval" : 5 , "rates" : {"count":0.5} , "group":"test2" , "file":"searches*start.b.stug.funmoods.com" , "hours":[5,2]}'""" % ( os.path.dirname(os.path.realpath(__file__)) , __file__)
	print "		this will look at s3://MYBUCKET/searches at server mapped to start.b.stug.funmoods.com taking 2 files. the one before 5 hours as master and the other as 2 as slave\n\n"
	print "***	Run in sql mode , comparing redshift table data with 2m range with offset of 2 days (172800) :"
	print """%s/%s  -q '{"group":"test1","seconds_offset" : 172800 , "seconds_range" : 120 , "table":"MYTABLE" , "host":"redshift01.infra-team.com" , "port":"5439"  ,"db":"MYDB" , "user":"MYDB","password":"MYPWD" , "rdbms":"postgresql" ,"time_field":"datetime" , "fields": ["b","bv","cc"] , "sumfields":{"uid":"dist" , "uage":"avg"} , "minval" : 20 , "splitter":"^^^" , "faults_min":5 , "rates" : {"count":0.5 , "uid" : 0.5 , "uage":0.8}}'\n""" % ( os.path.dirname(os.path.realpath(__file__)) , __file__)
	print "***      Run in sql mode , comparing Mysql table data with Fix times , with aggregation without comparing (monitor=true)"
	print """%s/%s -q '{"group":"test1", "fix_times" : ["2014-01-02 00:00:00","2014-01-02 23:59:59","2014-01-01 00:00:00","2014-01-01 23:59:59"] , "table":"MYTABLE" , "host":"localhost" , "port":"3306" ,"db":"MYDB" , "user":"MYUSER","password":"MYPWD" , "rdbms":"mysql" ,"time_field":"datetime" , "fields": ["b","bv","cc"] , "sumfields":{"uid":"dist" , "uage":"avg"} , "minval" : 2 , "splitter":"^^^" , "faults_min":5 , "rates" : {"count":0.9 , "uid" : 0.9 , "uage":0.8} , "monitor":"true"}'\n""" % ( os.path.dirname(os.path.realpath(__file__)) , __file__)
	print "***      Run in sql mode , comparing redshift table data between 2 entire dates 2013-12-25,2013-12-26 with filter set to p='funmoods'"
	print """%s/%s  -q '{"group":"test1", "sql":{"fix_times" : ["2013-12-25","2013-12-25","2013-12-26","2013-12-26"] , "table":"MYTABLE" , "host":"redshift01.infra-team.com" , "port":"5439"  ,"db":"icbi" , "user":"icbi","password":"UAx9O7kg49:5^Y5" , "rdbms":"postgresql" ,"time_field":"datetime"} , "fields": ["b","bv","cc"] , "sumfields":{"uid":"dist" } , "minval" : 100 , "faults_min":5 , "rates" : {"count":0.5 , "uid" : 0.5 } , "filter":{"p":"funmoods"}}'\n""" % ( os.path.dirname(os.path.realpath(__file__)) , __file__)	
	sys.exit(0)


##########################################################################
##########################################################################

(options, args) = parse_args()


if options.e or options.e == False : print_examples() 		# Not None !!
if options.s == None and options.ht == None and options.q == None : options.f = True	# default
if options.debug == "1" or options.debug == "true" or options.debug == False : options.debug = True
if options.test == "1" or options.test == "true" or options.test == False : 
	options.test = True
	options.debug = True

main = Main(options.debug)
if options.test : sys.exit(0)

#	Clear results.log
os.remove("../logs/results.log")
open("../logs/results.log","w").close()


if options.f:
	main.run()
elif options.ht:
	os.remove("../logs/groups.log")
	open("../logs/groups.log","w").close()

	main.run_single("head -%s" % ( options.ht ))
	main.run_single("tail -%s" % ( options.ht ))
	print "Waiting for Input..."
	while True :
		cmd = sys.stdin.readline()
		if cmd	and re.match(r'^\d+\n?$' , cmd):
			main.run_single("tail -%s" % (cmd.strip()))
			print "Waiting for Input..."

elif options.s:
	from s3cmp import *
	s3 = S3cmp( options.s , options.debug)
	s3.s3cmd()

elif options.q:
	q = SqlGroupManager(options.q , options.debug)
	q.pulse()

elif options.test:
                conf  = Configger(True)
                conf.parse_groups()
		sys.exit(0)
